package builder;/*
 * @auther 顶风少年
 * @mail dfsn19970313@foxmail.com
 * @date 2020-01-08 11:30
 * @notify
 * @version 1.0
 */

import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.Text;
import sqlnode.SqlNode;
import sqlnode.impl.IfSqlNode;
import sqlnode.impl.MixedSqlNode;
import sqlnode.impl.StaticTextSqlNode;
import sqlnode.impl.TextSqlNode;
import sqlsource.SqlSource;
import sqlsource.impl.DynamicSqlSource;
import sqlsource.impl.RawSqlSource;

import java.util.ArrayList;
import java.util.List;

public class XMLScriptBuilder {

    private boolean isDynamic = false;

    //解析标签体
    public SqlSource parseScriptNode(Element selectElement) throws Exception {
        MixedSqlNode mixedSqlNode = parseDynamicTags(selectElement);
        SqlSource sqlSource;
        if (isDynamic) {//如果包含${}或者其他的子标签则为动态的
            sqlSource = new DynamicSqlSource(mixedSqlNode);
        } else {//全部的sqlNode都是文本，并且只包含#{}
            sqlSource = new RawSqlSource(mixedSqlNode);
        }
        return sqlSource;
    }


    private MixedSqlNode parseDynamicTags(Element selectElement) {
        //存储一个 <select> 中的所有sqlNode
        List<SqlNode> sqlNodes = new ArrayList<>();
        //查询总结点数量
        int nodeCount = selectElement.nodeCount();
        //遍历全部的sql节点
        for (int i = 0; i < nodeCount; i++) {
            //获取当前节点
            Node node = selectElement.node(i);
            //如果是纯文本的
            if (node instanceof Text) {
                //拿到文本节点
                String sqlText = node.getText().trim();
                if (!sqlText.equals("")) {
                    //如果包含 ${} 则创建 TextSqlNode 该节点只包含文本和${}
                    if (sqlText.indexOf("${") > -1) {
                        //如果包含${}或者其他的子标签则为动态的
                        isDynamic = true;
                        //将TextSqlNode添加到节点集合中
                        sqlNodes.add(new TextSqlNode(sqlText));
                    } else {
                        //将StaticTextSqlNode添加到节点集合中
                        sqlNodes.add(new StaticTextSqlNode(sqlText));
                    }
                }
            } else if (node instanceof Element) {
                //如果包含${}或者其他的子标签则为动态的
                isDynamic = true;
                //拿到节点名称
                String nodeName = node.getName();
                //如果是 if则表示是if标签
                if (nodeName.equals("if")) {
                    //将node转换成element
                    Element element = (Element) node;
                    //拿到if的条件
                    String test = element.attributeValue("test");
                    /*
                    此处递归调用，因为if标签中还有子节点
                    设sql为
                    select * from user
                    <if test='name!=null and name!='''>
                        and name = #{name}
                    </if>
                    此时 select * from user 已经转换成了sqlNode
                    接下来的if标签，里边也包含子节点，所以递归，
                    第二次进入 （parseDynamicTags）
                    会创建一个StaticTextSqlNode，将该SqlNode添加到
                     List<SqlNode> sqlNodes = new ArrayList<>();
                     而这个集合最终会被封装成一个MixedSqlNode返回到第一次
                     调用（parseDynamicTags），所以此处使用
                     MixedSqlNode接收，并将该MixedSqlNode传递给IfSqlNode，然后
                     添加到sqlNodes中
                    */
                    MixedSqlNode mixedSqlNode = parseDynamicTags(element);
                    sqlNodes.add(new IfSqlNode(test, mixedSqlNode));
                }
            }
        }
        //返回节点集合包装类
        return new MixedSqlNode(sqlNodes);
    }
}
